extends "res://scene/character/character_base.gd"

@onready var anim: AnimatedSprite2D = get_node_or_null("AnimatedSprite2D")
@onready var attack_area: Area2D = get_node_or_null("AttackArea")

var enemies_in_range: Array[Node2D] = []
var facing_right: bool = true
var _attacking: bool = false
var _attack_cycle_started: bool = false

func _ready() -> void:
	self_group = "army"
	max_health = 200.0
	attack_damage = 12.0
	attack_interval = 0.8
	move_speed = 160.0
	if attack_area:
		attack_area.area_entered.connect(_on_attack_area_entered)
		attack_area.area_exited.connect(_on_attack_area_exited)
	if anim:
		anim.frame_changed.connect(_on_anim_frame_changed)

func _physics_process(delta: float) -> void:
	attack_timer = max(0.0, attack_timer - delta)
	if _attacking:
		velocity = Vector2.ZERO
		if anim and anim.animation != "attack_right":
			anim.play("attack_right")
		move_and_slide()
		return
	var input_vec := Vector2.ZERO
	if Input.is_key_pressed(KEY_W):
		input_vec.y -= 1.0
	if Input.is_key_pressed(KEY_S):
		input_vec.y += 1.0
	if Input.is_key_pressed(KEY_A):
		input_vec.x -= 1.0
	if Input.is_key_pressed(KEY_D):
		input_vec.x += 1.0
	if input_vec.length() > 0.0:
		velocity = input_vec.normalized() * move_speed
	else:
		velocity = Vector2.ZERO
	if anim:
		if velocity.x > 0.0:
			anim.flip_h = false
			facing_right = true
		elif velocity.x < 0.0:
			anim.flip_h = true
			facing_right = false
		if velocity.length() > 0.0:
			anim.play("run_right")
		else:
			anim.play("idle")
	if Input.is_key_pressed(KEY_J) and attack_timer <= 0.0 and not _attacking:
		_attacking = true
		_attack_cycle_started = false
		if anim:
			anim.flip_h = not facing_right
			anim.play("attack_right")
		_start_attack()
	move_and_slide()

func _start_attack() -> void:
	if attack_timer > 0.0:
		return
	super.attack()
	var t := _choose_target_in_range()
	if t != null:
		_do_attack(t)

func _choose_target_in_range() -> Node2D:
	var nearest: Node2D = null
	var min_d: float = 1e20
	for e in enemies_in_range:
		if is_instance_valid(e):
			var d: float = global_position.distance_to(e.global_position)
			if d < min_d:
				min_d = d
				nearest = e
	return nearest

func _do_attack(t: Node2D) -> void:
	if t == null or not is_instance_valid(t):
		return
	if t.has_method("get_damage"):
		t.get_damage(attack_damage, self)

func _on_attack_area_entered(area: Area2D) -> void:
	var parent := area.get_parent()
	if parent and parent is Node2D and parent.is_in_group("enemy"):
		if not enemies_in_range.has(parent):
			enemies_in_range.append(parent)

func _on_attack_area_exited(area: Area2D) -> void:
	var parent := area.get_parent()
	if parent and parent is Node2D:
		enemies_in_range.erase(parent)

func _on_anim_frame_changed() -> void:
	if not anim:
		return
	if _attacking and anim.animation == "attack_right":
		if anim.frame == 0:
			if not _attack_cycle_started:
				_attack_cycle_started = true
			else:
				_attacking = false
